<template>
  <h2 class="text-base font-semibold leading-7 text-gray-900">
    {{ $t('pageLdap.settings') }}
  </h2>
  <div>{{ $t('pageLdap.form.ldapAuthentication') }}</div>
  <el-checkbox
    v-model="form.ldapAuthenticationEnabled"
    @change="onChangeldapAuthenticationEnabled"
  >
    {{ $t('global.action.enable') }}
  </el-checkbox>
  <el-form
    class="mb-10"
    :disabled="!form.ldapAuthenticationEnabled"
    :model="form"
    :rules="rules"
  >
    <el-collapse v-model="activeNames">
      <el-collapse-item
        :title="$t('pageLdap.form.secureLdapUsingSsl')"
        name="1"
      >
        <h2 class="text-base font-semibold leading-7 text-gray-900">
          {{ $t('pageLdap.form.secureLdapUsingSsl') }}
        </h2>
        <div>{{ $t('pageLdap.form.secureLdapHelper') }}</div>
        <el-checkbox
          v-model="form.secureLdapEnabled"
          :disabled="!caCertificateExpiration || !ldapCertificateExpiration"
        >
          {{ $t('global.action.enable') }}
        </el-checkbox>
        <dl>
          <dt>{{ $t('pageLdap.form.caCertificateValidUntil') }}</dt>
          <dd v-if="caCertificateExpiration">
            {{ globalStore.formatDate(caCertificateExpiration) }}
          </dd>
          <dd v-else>--</dd>
          <dt>{{ $t('pageLdap.form.ldapCertificateValidUntil') }}</dt>
          <dd v-if="ldapCertificateExpiration">
            {{ globalStore.formatDate(ldapCertificateExpiration) }}
          </dd>
          <dd v-else>--</dd>
        </dl>
      </el-collapse-item>
      <el-collapse-item :title="$t('pageLdap.form.serviceType')" name="2">
        <el-row>
          <el-radio-group
            v-model="form.activeDirectoryEnabled"
            :label="$t('pageLdap.form.serviceType')"
          >
            {{ form.activeDirectoryEnabled }}
            <el-radio
              data-test-id="ldap-radio-activeDirectoryEnabled"
              :value="false"
              @change="onChangeServiceType"
            >
              OpenLDAP
            </el-radio>
            <el-radio
              data-test-id="ldap-radio-activeDirectoryEnabled"
              :value="true"
              @change="onChangeServiceType"
            >
              Active Directory
            </el-radio>
          </el-radio-group>
        </el-row>
        <el-row class="*:mb-5 *:pr-10">
          <el-col :span="8">
            <div>{{ $t('pageLdap.form.serverUri') }}</div>
            <el-input
              v-model="form.serverUri"
              style="max-width: 600px"
              placeholder="Please input"
            >
              <template #prepend>{{ ldapProtocol }}</template>
            </el-input>
          </el-col>
          <el-col :span="8">
            <div>{{ $t('pageLdap.form.bindDn') }}</div>
            <el-input
              v-model="form.bindDn"
              style="max-width: 600px"
              placeholder="Please input"
            >
            </el-input>
          </el-col>
          <el-col :span="8">
            <div>{{ $t('pageLdap.form.bindPassword') }}</div>
            <el-input
              v-model="form.bindPassword"
              style="max-width: 600px"
              placeholder="Please input"
            >
            </el-input>
          </el-col>
          <el-col :span="8">
            <div>{{ $t('pageLdap.form.baseDn') }}</div>
            <el-input
              v-model="form.baseDn"
              style="max-width: 600px"
              placeholder="Please input"
            >
            </el-input>
          </el-col>
          <el-col :span="8">
            <div>
              {{ $t('pageLdap.form.userIdAttribute') }} -
              <span class="form-text inline">
                {{ $t('global.form.optional') }}
              </span>
            </div>
            <el-input
              v-model="form.userIdAttribute"
              style="max-width: 600px"
              placeholder="Please input"
            >
            </el-input>
          </el-col>
          <el-col :span="8">
            <div>
              {{ $t('pageLdap.form.groupIdAttribute') }} -
              <span class="form-text inline">
                {{ $t('global.form.optional') }}
              </span>
            </div>
            <el-input
              v-model="form.groupIdAttribute"
              style="max-width: 600px"
              placeholder="Please input"
            >
            </el-input>
          </el-col>
        </el-row>
      </el-collapse-item>
    </el-collapse>
    <el-button
      class="mt-5"
      :type="form.ldapAuthenticationEnabled ? 'primary' : 'info'"
      @click="handleSubmit"
    >
      {{ $t('global.action.saveSettings') }}
    </el-button>
  </el-form>

  <h2 class="text-base font-semibold leading-7 text-gray-900">
    {{ $t('pageLdap.roleGroups') }}
  </h2>
  <table-role-groups />
</template>

<script setup lang="ts">
import _ from 'lodash';
import { useLdapStore } from '@/store/UserSecurity/LDAP/LdapStore';
import { useCertificatesStore } from '@/store/UserSecurity/Certificates/CertificatesStore';
import { useGlobalStore } from '@/store/global';
import useVuelidateTool from '@/hooks/useVuelidateTool';
import tableRoleGroups from './TableRoleGroups.vue';

const { useVuelidate, requiredIf, elementInputValidator } = useVuelidateTool();
const ldapStore = useLdapStore();
const certificatesStore = useCertificatesStore();
const globalStore = useGlobalStore();

await ldapStore.getAccountSettings();
await certificatesStore.getCertificates();

const setFormValues = (serviceType?: any) => {
  if (!serviceType) {
    serviceType = isActiveDirectoryEnabled.value
      ? activeDirectory.value
      : ldap.value;
  }
  const {
    serviceAddress = '',
    bindDn = '',
    baseDn = '',
    userAttribute = '',
    groupsAttribute = '',
  } = serviceType;
  const secureLdap =
    serviceAddress && serviceAddress.includes('ldaps://') ? true : false;
  const serverUri = serviceAddress
    ? serviceAddress.replace(/ldaps?:\/\//, '')
    : '';
  form.value.secureLdapEnabled = secureLdap;
  form.value.serverUri = serverUri;
  form.value.bindDn = bindDn;
  form.value.bindPassword = '';
  form.value.baseDn = baseDn;
  form.value.userIdAttribute = userAttribute;
  form.value.groupIdAttribute = groupsAttribute;
};

const isServiceEnabled = computed(() => ldapStore.isServiceEnabled);
const isActiveDirectoryEnabled = computed(
  () => ldapStore.isActiveDirectoryEnabled,
);
const ldap = computed(() => ldapStore.ldap);
const activeDirectory = computed(() => ldapStore.activeDirectory);
const sslCertificates = computed(() => certificatesStore.allCertificates);
const caCertificateExpiration = computed(() => {
  const caCertificate = _.find(sslCertificates.value, {
    type: 'TrustStore Certificate',
  });
  if (caCertificate === undefined) return null;
  return caCertificate.validUntil;
});
const ldapCertificateExpiration = computed(() => {
  const ldapCertificate = _.find(sslCertificates.value, {
    type: 'LDAP Certificate',
  });
  if (ldapCertificate === undefined) return null;
  return ldapCertificate.validUntil;
});

const form = ref({
  ldapAuthenticationEnabled: ldapStore.isServiceEnabled,
  secureLdapEnabled: false,
  activeDirectoryEnabled: ldapStore.isActiveDirectoryEnabled,
  serverUri: '',
  bindDn: '',
  bindPassword: '',
  baseDn: '',
  userIdAttribute: '',
  groupIdAttribute: '',
});

setFormValues();

const activeNames = ref(['1', '2']);

const v$ = useVuelidate(
  {
    ldapAuthenticationEnabled: {},
    secureLdapEnabled: {},
    activeDirectoryEnabled: {
      required: requiredIf(function () {
        return form.value.ldapAuthenticationEnabled;
      }),
    },
    serverUri: {
      required: requiredIf(function () {
        return form.value.ldapAuthenticationEnabled;
      }),
    },
    bindDn: {
      required: requiredIf(function () {
        return form.value.ldapAuthenticationEnabled;
      }),
    },
    bindPassword: {
      required: requiredIf(function () {
        return form.value.ldapAuthenticationEnabled;
      }),
    },
    baseDn: {
      required: requiredIf(function () {
        return form.value.ldapAuthenticationEnabled;
      }),
    },
    userIdAttribute: {},
    groupIdAttribute: {},
  },
  form,
);

const rules = computed(() => {
  return {
    activeDirectoryEnabled: [
      {
        trigger: 'blur',
        validator: elementInputValidator.value(v$, 'activeDirectoryEnabled'),
      },
    ],
    serverUri: [
      {
        trigger: 'blur',
        validator: elementInputValidator.value(v$, 'serverUri'),
      },
    ],
    bindDn: [
      {
        trigger: 'blur',
        validator: elementInputValidator.value(v$, 'bindDn'),
      },
    ],
    bindPassword: [
      {
        trigger: 'blur',
        validator: elementInputValidator.value(v$, 'bindPassword'),
      },
    ],
    baseDn: [
      {
        trigger: 'blur',
        validator: elementInputValidator.value(v$, 'baseDn'),
      },
    ],
  };
});

const ldapProtocol = computed(() =>
  form.value.secureLdapEnabled ? 'ldaps://' : 'ldap://',
);

watch(isServiceEnabled, (value: boolean) => {
  form.value.ldapAuthenticationEnabled = value;
});
watch(isActiveDirectoryEnabled, (value: boolean) => {
  form.value.activeDirectoryEnabled = value;
  setFormValues();
});

const handleSubmit = () => {
  v$.value.$touch();
  if (v$.value.$invalid) return;
  const data = {
    serviceEnabled: form.value.ldapAuthenticationEnabled,
    activeDirectoryEnabled: form.value.activeDirectoryEnabled,
    serviceAddress: `${ldapProtocol.value}${form.value.serverUri}`,
    bindDn: form.value.bindDn,
    bindPassword: form.value.bindPassword,
    baseDn: form.value.baseDn,
    userIdAttribute: form.value.userIdAttribute,
    groupIdAttribute: form.value.groupIdAttribute,
  };
  ldapStore
    .saveAccountSettings(data)
    .then((success: string) => {
      ElNotification({
        type: 'success',
        message: success,
      });
    })
    .catch(({ message }: { message: string }) => {
      ElNotification({
        type: 'error',
        message: message,
      });
    })
    .finally(() => {
      form.value.bindPassword = '';
      v$.value.form.$reset();
    });
};
const onChangeServiceType = (isActiveDirectoryEnabled: boolean) => {
  v$.value.activeDirectoryEnabled.$touch();
  const serviceType = isActiveDirectoryEnabled
    ? activeDirectory.value
    : ldap.value;
  // Set form values according to user selected
  // service type
  setFormValues(serviceType);
};
const onChangeldapAuthenticationEnabled = (isServiceEnabled: boolean) => {
  v$.value.ldapAuthenticationEnabled.$touch();
  if (!isServiceEnabled) {
    // Request will fail if sent with empty values.
    // The frontend only checks for required fields
    // when the service is enabled. This is to prevent
    // an error if a user clears any properties then
    // disables the service.
    setFormValues();
  }
};
</script>
